
const {ccclass, property} = cc._decorator;
import PlayerClass  from './Player';
import StarClass from './Star';

@ccclass
export default class GameClass extends cc.Component {
    // 这个属性引用了星星预制资源
    @property({
        type: cc.Prefab,
    })
    starPrefab: cc.Prefab = null;

    // 星星产生后消失时间的随机范围
    @property
    maxStarDuration: number =  0;
    @property
    minStarDuration: number =  0;
    
    // 地面节点，用于确定星星生成的高度
    @property({
        type: cc.Node,
    })
    ground: cc.Node = null;

    // player 节点，用于获取主角弹跳的高度，和控制主角行动开关
    @property({
        type: cc.Node,
    })
    player: cc.Node = null;
    
    // 分数
    @property({
        type: cc.Label
    })
    scoreDisplay: cc.Label = null;

    // 初始化计分
    @property
    score: number = 0;
    // 初始化计时器
    @property
    timer: number = 0;

    @property
    starDuration: number = 0;
    
    // 得分音效资源
    @property({
        type: cc.AudioClip,
    })
    scoreAudio: cc.AudioClip = null;
    // LIFE-CYCLE CALLBACKS:

    public onLoad (): void {
        // 生成一个新的星星
        this.spawnNewStar();
    }

    public spawnNewStar() {
        // 使用给定的模板在场景中生成一个新节点, 动态的克隆场景中的已有节点，我们可以通过 cc.instantiate 方法完成
        let newStar = cc.instantiate(this.starPrefab);
        // 将新增的节点添加到 Canvas 节点下面, addChild 添加子节点，并且可以修改该节点的 局部 Z 顺序和名字。
        this.node.addChild(newStar);
        // 为星星设置一个随机位置, setPosition 设置节点在父节点坐标系中的位置。
        newStar.setPosition(this.getNewStarPosition())

        // 在星星组件上暂存 Game 对象的引用
        newStar.getComponent(StarClass).game = this;

        // 重置计时器，根据消失时间范围随机取一个值
        this.starDuration = this.minStarDuration + Math.random() * (this.maxStarDuration - this.minStarDuration);
        this.timer = 0;
    }
    
    public getNewStarPosition(): cc.Vec2 {
        // 获取地平面的 y 轴坐标
        let groundY = this.ground.y + this.ground.height/2;

        let randX: number = 0;
        // 根据地平面位置和主角跳跃高度，随机得到一个星星的 y 坐标, getComponent 获取节点上指定类型的组件，如果节点有附加指定类型的组件，则返回，如果没有则为空。
        let randY = groundY + Math.random() * this.player.getComponent(PlayerClass).jumpHeight + 50;

        // 根据屏幕宽度，随机得到一个星星 x 坐标
        let maxX = this.node.width / 2;
        randX = (Math.random() - 0.5) * 2 * maxX;

        // 返回星星坐标
        return cc.v2(randX, randY);
    }
    // public start(): void {  
    // }
    public update(dt: number): void {
        // 每帧更新计时器，超过限度还没有生成新的星星
        // 就会调用游戏失败逻辑
        if (this.timer > this.starDuration) {
            this.gameOver();
            return;
        }
        this.timer += dt;
    }

    public gainScore(): void {
        this.score += 1;
        // 更新 scoreDisplay Label 的文字
        this.scoreDisplay.string = 'Score: ' + this.score;
        // 播放得分音效
        cc.audioEngine.playEffect(this.scoreAudio, false);
    }

    public gameOver() {
        //停止 player 节点的跳跃动作
        this.player.stopAllActions();
        // 重新加载游戏场景 game
        cc.director.loadScene('game');
    }
}
